#include "syscall.h"
#include "usercommon.h"


long strlen(char* str)
{
    long size = 0;
    while( str[size] != '\0')
        size ++;
    return size;
}

char* strrev(char* start)
{
    long len = strlen(start);
    long i = 0;
    for (i =0; i < (len/2); i++)
    {
        char* left = start + i;
        char* right = start + (len - i - 1);
        char temp = *left;
        *left =  *right;
        *right = temp;
    }
    return start;
}
char* strcpy(char* to, char* from)
{
    while (*from != '\0')
    {
        *to = *from;
        to++;
        from++;
    }
    *to = '\0';
    return to;
}
void localPrintf(char* toPrint)
{
	Write(toPrint, strlen(toPrint),ConsoleOutput);
}
void printf(char* toPrint)
{
	Acquire(printLock);
    localPrintf(toPrint);
    Release(printLock);
}

void printf_WithSize(char* toPrint, int size)
{
    Write(toPrint, size,ConsoleOutput);
}

char* ConvertToString_long(long toConvert, int* size)
{
    int isNegative=0;
    int pos = 0;
    if (toConvert < 0)
    {
        toConvert *= -1;
        isNegative = 1;
    }
    if (toConvert == 0)
    {
        localBuffer[pos] ='0';
        pos++;
        localBuffer[pos] ='\0';
        *size = pos;
        return localBuffer;
    }
    while (toConvert != 0)
    {
        int a = toConvert % 10;
        localBuffer[pos] = a + '0';
        pos++;
        toConvert /= 10;
    }
    if (isNegative == 1)
    {
        localBuffer[pos] = '-';
        pos++;
    }
    localBuffer[pos] = '\0';
    *size = pos;
    return strrev(localBuffer);
}

int i;

void printf_long(long toPrint)
{
    int size = 0;
    strcpy(localBuffer, ConvertToString_long(toPrint,&size));
    printf_WithSize(localBuffer, size);


}


void printf_int(int toPrint)
{
    printf_long((long)toPrint);
}

/*Returns the threadID of the newly generated thread*/
int CallFork(char *name, void (*func)())
{
    return Fork(name, strlen(name), func);
}

int CallExec(char* name)
{
	return Exec(name, strlen(name));
}

void printf_1 (char* one) {
	localPrintf(one);
}


void printf_2(char* one, int two) {
	Acquire(printLock);
	localPrintf(one);
	printf_int(two);
	Release(printLock);
}

void printf_3(char* one, int two, char* three) {
	Acquire(printLock);
	localPrintf(one);
	printf_int(two);
	localPrintf(three);
    Release(printLock);
}

void printf_4(char* one, int two, char* three, int four) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    Release(printLock);
}

void printf_5(char* one, int two, char* three, int four, char* five) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    localPrintf(five);
    Release(printLock);
}

void printf_6(char* one, int two, char* three, int four, char* five, int six) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    localPrintf(five);
    printf_int(six);
    Release(printLock);

}

void printf_7(char* one, int two, char* three, int four, char* five, int six, char* seven) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    localPrintf(five);
    printf_int(six);
    localPrintf(seven);
    Release(printLock);
}

void printf_8(char* one, int two, char* three, int four, char* five, int six, char* seven, int eight) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    localPrintf(five);
    printf_int(six);
    localPrintf(seven);
    printf_int(eight);
    Release(printLock);
}

void printf_9(char* one, int two, char* three, int four, char* five, int six, char* seven, int eight, char* nine) {
	Acquire(printLock);
	localPrintf(one);
    printf_int(two);
    localPrintf(three);
    printf_int(four);
    localPrintf(five);
    printf_int(six);
    localPrintf(seven);
    printf_int(eight);
    localPrintf(nine);
    Release(printLock);
}

void printf_10(char* one, int two, char* three, int four, char* five, int six, char* seven, int eight, char* nine, int ten) {
	Acquire(printLock);
	localPrintf(one);
	printf_int(two);
	localPrintf(three);
	printf_int(four);
	localPrintf(five);
	printf_int(six);
	localPrintf(seven);
	printf_int(eight);
	localPrintf(nine);
    printf_int(ten);
    Release(printLock);
}

void printf_11(char* one, int two, char* three, int four, char* five, int six, char* seven, int eight, char* nine, int ten, char* eleven) {
	Acquire(printLock);
	localPrintf(one);
	printf_int(two);
	localPrintf(three);
	printf_int(four);
	localPrintf(five);
	printf_int(six);
	localPrintf(seven);
	printf_int(eight);
	localPrintf(nine);
    printf_int(ten);
    localPrintf(eleven);
    Release(printLock);
}
